/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Parser;

import Graph.*;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.Attributes;

/**
 *
 * @author oliviersputael
 */
public class NodesParser extends DefaultHandler {
	public NodesParser () throws SAXException {
		super();
		reader = XMLReaderFactory.createXMLReader();
		reader.setContentHandler(this);
		reader.setErrorHandler(this);
		nodes = new ArrayList<Node>();
		strVars = new ArrayList<String>();
		gotLastInfo = false;
		tempInstr = null;
	}
	
	public List<Node> getNodesFromFile (String filename, List<Variables> vars, List<Color> cols) throws FileNotFoundException, IOException, SAXException {
		nodes.clear();
		this.vars = vars;
		this.colors = cols;
		file = new FileReader(filename);
		reader.parse(new InputSource(file));
		
		return nodes;
	}
	
	/*
	 * Event handlers
	 */
	
	@Override
	public void startDocument () {
		// nothing to do
	}
	
	@Override
	public void endDocument () {
		// nothing to do
	}
	
	@Override
	public void startElement (String uri, String name, String qName, Attributes attr) {
		lastOpenedTag = qName;
		gotLastInfo = false;
	}
	
	@Override 
	public void endElement (String uri, String name, String qName) {
		if (qName.equals("nodes")) {
			List<Variables> nodeVars = new ArrayList<Variables>();
		
			for (String s : strVars) {
				for (Variables v : vars) {
					if (v.getName().equals(s))
						nodeVars.add(v);
				}
			}
			
			boolean found = false;
			Color c = null;
			for (int i = 0; i < colors.size() && !found; i++) {
				if (colors.get(i).getName().equals(color)) {
					found = true;
					c = colors.get(i);
				}
			}
			
			strVars.clear();
			Instructions temp = new Instructions(atomic, label, nodeVars, position, new ArrayList<Instructions>());
			if (tempInstr != null) {
				int endIndexPosTemp = temp.getPosition().length() - 4 ;
				int endIndexPosTInstr = tempInstr.getPosition().length() - 4;
				String tInstrPos = tempInstr.getPosition();
				String tempPos = temp.getPosition();
				// The basic next : next in the same sequence, when, method
				if (tInstrPos.equals(position))
					tempInstr.addNext(temp);
				// the WHEN next : next of the WHEN condition
				else if (tempInstr.getLabel().substring(0, 4).equals("WHEN") && tempPos.equals(tempInstr.getLabel()))
					tempInstr.addNext(temp);
				// the IF next : next of the IF condition
				else if (tempInstr.getLabel().substring(0, 2).equals("IF") && tempPos.equals(tempInstr.getLabel()))
					tempInstr.addNext(temp);
				else if (tempInstr.getLabel().substring(0, 5).equals("WHILE") && tempPos.equals(tempInstr.getLabel()))
					tempInstr.addNext(temp);
				else if (tInstrPos.substring(0, 5).equals("WHILE") && !tInstrPos.equals(tempPos)) {
					boolean F = false;
					for (int i = 0; i < nodes.size() && !F; i++) {
						if (nodes.get(i).getInstruction().getLabel().equals(tInstrPos)) {
							F = true;
							nodes.get(i).getInstruction().addNext(temp);
						}
					}
				}
				// the IF-ELSE next : next of the last instr in the IF
				else if (tempPos.substring(0, 2).equals("IF") && tempPos.substring(endIndexPosTemp, tempPos.length()).equals("ELSE")) {
					String ifLabel = tempPos.substring(0, endIndexPosTemp) + "THEN";
					boolean F = false;
					for (int i = 0; i < nodes.size() && !F; i++) {
						if (nodes.get(i).getInstruction().getLabel().equals(ifLabel)) {
							F = true;
							nodes.get(i).getInstruction().addNext(temp);
						}
					}
				}
				else if (tInstrPos.substring(0, 2).equals("IF") && !tInstrPos.equals(tempPos)) {
					tempInstr.addNext(temp);
					String ifLabel = tInstrPos.substring(0, endIndexPosTInstr) + "THEN";
					boolean foundIF = false;
					boolean foundLastIF = false;
					for (int i = 0; i < nodes.size() && (!foundIF || !foundLastIF); i++) {
						if (nodes.get(i).getInstruction().getLabel().equals(ifLabel)) {
							foundIF = true;
							nodes.get(i).getInstruction().addNext(temp);
						}
						if (nodes.get(i).getInstruction().getPosition().equals(ifLabel) && nodes.get(i).getInstruction().getNext().isEmpty()) {
							foundLastIF = true;
							nodes.get(i).getInstruction().addNext(temp);
						}
					}
				}
				
				/*else if (tInstrPos.substring(0, 2).equals("IF") &&
						 temp.getPosition().substring(0, endIndexPosTemp).equals(tempInstr.getPosition().substring(0, endIndexPosTInstr)))
					tempInstr.addNext(temp);*/
			}
			tempInstr = temp;
			nodes.add(new Node(temp, c)); 
		}
	}
	
	@Override
	public void characters (char[] c, int start, int length) {
		if (!gotLastInfo) {
			if (lastOpenedTag.equals("label")) {
				label = String.copyValueOf(c, start, length);
				gotLastInfo = true;
			}
			else if (lastOpenedTag.equals("name")) { // in <vars>
				String temp = String.copyValueOf(c, start, length);
				if (!temp.equals("#NULL#"))
					strVars.add(temp);
				gotLastInfo = true;
			}
			else if (lastOpenedTag.equals("position")) {
				position = String.copyValueOf(c, start, length);
				gotLastInfo = true;
			}
			else if (lastOpenedTag.equals("distrib")) {
				atomic = String.copyValueOf(c, start, length).equals("atomic");
				gotLastInfo = true;
			}
			else if (lastOpenedTag.equals("color")) {
				color = String.copyValueOf(c, start, length);
				gotLastInfo = true;
			}
			else {
				// Nothing to do: junk chars
			}
		}
	}
	
	private XMLReader reader;
	private FileReader file;
	private List<Node> nodes;
	private String lastOpenedTag;
	private boolean gotLastInfo;
	private String label;
	private String position;
	private boolean atomic;
	private List<String> strVars;
	private List<Variables> vars;
	private List<Color> colors;
	private Instructions tempInstr;
	private String color;
}
